#pragma once

#define DEBUG_OUT(...) RCLCPP_INFO(rclcpp::get_logger("io_module"), __VA_ARGS__)
#define DEBUG_STREAM_OUT(info) \
    RCLCPP_INFO_STREAM(rclcpp::get_logger("io_module"), info)
#define DEBUG_OUT_THROTTLE(clock,s,info) \
    RCLCPP_INFO_STREAM_THROTTLE(rclcpp::get_logger("io_module"), clock, s, info) 
#define DEBUG_WARN_OUT(info) \
    RCLCPP_WARN_STREAM(rclcpp::get_logger("io_module"), info)
#define DEBUG_ERROR_OUT(info) \
    RCLCPP_ERROR_STREAM(rclcpp::get_logger("io_module"), info)
#define DEBUG_FATAL_OUT(info) \
    RCLCPP_FATAL_STREAM(rclcpp::get_logger("io_module"), info)

#define DEBUG_WARN_ON_TRANSITION(condition, message) \
    do { \
        static bool last_##condition = true; \
        static bool triggered_##condition = false; \
        if (!(condition)) { \
            if (last_##condition && !triggered_##condition) { \
                DEBUG_WARN_OUT(message); \
                triggered_##condition = true; \
            } \
            last_##condition = false; \
        } else { \
            last_##condition = true; \
            triggered_##condition = false; \
        } \
    } while (0)

#define BIT(x) (((uint64_t)1) << (x))
#define TestBit(x, i) ((x & BIT(i)) != 0)
#define SET_BIT(x, n) (x | ((uint64_t)(1) << n))
#define CLEAR_BIT(x, n) (x & ~((uint64_t)(1) << n))
#define NEGATION_BIT(x, n) (x ^ ((uint64_t)(1) << n))

enum SoundMode
{
    SOUND_SILENT = 0,
    SOUND_RUN = 1,
    SOUND_ALARM = 2,
    SOUND_OBSTACLE = 3,
    SOUND_SPIN = 4
};

enum MoveDirTag
{
    FORWARD,
    BACKWARD,
    LEFTWARD = 0,
    RIGHTWARD = 1
};

enum BusType
{
    Modbus_tcp,
    Modbus_rs485,
    Modbus_rs232,
    canopen_401,
};
